package com.scfire.security


import org.codehaus.groovy.runtime.HandleMetaClass
import org.slf4j.Logger
import org.slf4j.LoggerFactory


public class ExceptionJdk17Workaround {
	public static final String MODULE = ExceptionJdk17Workaround.class.getName();
	public static final Logger log = LoggerFactory.getLogger(MODULE);

	static void installWorkaround() {
		if(getJavaVersionAsDouble() >= 1.7) {
			def metaClass = Exception.metaClass

			if(metaClass instanceof HandleMetaClass)
				metaClass = metaClass.replaceDelegate()

			if(metaClass.hasProperty("__gluExceptionJdk17Workaround")) {
				log.info "Running with jdk1.7: groovy Exception workaround already installed"
			}
			else {
				def field = MetaClassImpl.class.getDeclaredField('constructors')
				field.setAccessible(true)
				def constructors = field.get(metaClass)

				int jdk7ConstructorIdx = -1

				constructors.array.eachWithIndex { elt, idx ->
					if(elt==null){

					}
					else if(elt.cachedConstructor.parameterTypes.size() == 4)
						jdk7ConstructorIdx = idx
				}

				if(jdk7ConstructorIdx != -1) {
					constructors.remove(jdk7ConstructorIdx)
					// this has 2 purposes:
					// 1) allowing to check the workaround
					// 2) making sure that the metaclass is no longer a weak reference, hence is not garbage collected!
					metaClass.__gluExceptionJdk17Workaround = true
					log.info "Running with jdk1.7: installed groovy Exception workaround"
				}
			}

			// making sure the workaround is in place...
			if(!new Exception().__gluExceptionJdk17Workaround)
				throw new RuntimeException("groovy exception workaround not set properly!!!")
		}
		else {
			log.debug "Running with jdk1.6: no workaround necessary"
		}
	}

	static double getJavaVersionAsDouble() {
		def version = System.getProperty("java.version")
		try {
			Double.parseDouble(version.split('\\.')[0..1].join('.'))
		}
		catch(NumberFormatException e) {
			e.printStackTrace()
			return 1.6;
		}
	}
}
